﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.UI;
using System.Collections;
using System.Linq.Expressions;
//using Microsoft.Web.Mvc.Internal;
using System.Reflection;
using System.Web.Mvc.Ajax;
using System.Web.Routing;
using Htse.Blue.Models;
using System.Linq.Dynamic;
using Htse.Blue.Helpers;

namespace Htse.Blue.Helpers
{
	public static class DataGridHelper
	{
		public static string DataGrid<T>(this HtmlHelper helper) where T : class
		{
			return DataGrid<T>(helper, null, new List<DataGridColumn<T>>(), null);
		}

		public static string DataGrid<T>(this HtmlHelper helper, PagedList<T> data) where T : class
		{
			return DataGrid<T>(helper, data, new List<DataGridColumn<T>>(), null);
		}

		public static string DataGrid<T>(
			this HtmlHelper helper,
			PagedList<T> data,
			IList<DataGridColumn<T>> dataColumns)
			where T : class
		{
			return DataGrid<T>(helper, data, dataColumns, null);
		}

		public static string DataGrid<T>(
			this HtmlHelper helper,
			PagedList<T> data,
			IList<DataGridColumn<T>> dataColumns,
			DataGridEditColumn<T> editColumn)
			where T : class
		{
			return DataGrid<T>(helper, data, dataColumns, editColumn, null);
		}

		public static string DataGrid<T>(
			this HtmlHelper helper,
			PagedList<T> data,
			IList<DataGridColumn<T>> dataColumns,
			DataGridEditColumn<T> editColumn,
			DataGridDeleteColumnBase<T> deleteColumn)
			where T : class
		{
			return DataGrid<T>(helper, data, dataColumns, editColumn, deleteColumn, false, null);
		}

		public static string DataGrid<T>(
			this HtmlHelper helper,
			PagedList<T> data,
			IList<DataGridColumn<T>> dataColumns,
			DataGridEditColumn<T> editColumn,
			DataGridDeleteColumnBase<T> deleteColumn,
			bool ajaxSupport,
			string divToUpdate)
			where T : class
		{
			if (data == null)
				data = (PagedList<T>)helper.ViewData.Model;

			// Get column names  
			if (dataColumns.Count == 0)
			{
				foreach (string propertyName in typeof(T).GetProperties().Select(p => p.Name).ToArray())
				{
					//columns.Add(new DataGridHelperColumn<string>(propertyName, propertyName, null));
				}
			}

			// Create HtmlTextWriter  
			var writer = new HtmlTextWriter(new StringWriter());

			// Open table tag  
			writer.RenderBeginTag(HtmlTextWriterTag.Table);

			// Render table header  
			writer.RenderBeginTag(HtmlTextWriterTag.Thead);
			RenderHeader(helper, writer, dataColumns, data.Filter, editColumn, deleteColumn, ajaxSupport, divToUpdate);
			writer.RenderEndTag();

			// Render table body  
			writer.RenderBeginTag(HtmlTextWriterTag.Tbody);
			foreach (var item in data)
			{
				RenderRow<T>(helper, writer, dataColumns, item, editColumn, deleteColumn);
			}

			RenderPagerRow<T>(
				helper,
				writer,
				data,
				dataColumns.Count + (editColumn != null ? 1 : 0) + (deleteColumn != null ? 1 : 0),
				ajaxSupport,
				divToUpdate);

			writer.RenderEndTag();

			// Close table tag  
			writer.RenderEndTag();

			// Return the string  
			return writer.InnerWriter.ToString();
		}

		private static void RenderHeader<T>(
			HtmlHelper helper,
			HtmlTextWriter writer,
			IList<DataGridColumn<T>> dataColumns,
			string filter,
			DataGridEditColumn<T> editColumn,
			DataGridDeleteColumnBase<T> deleteColumn,
			bool ajaxSorting,
			string divToUpdate)
			where T : class
		{
			writer.RenderBeginTag(HtmlTextWriterTag.Tr);

			if (editColumn != null)
			{
				if (editColumn.Width.HasValue)
				{
					writer.AddAttribute(HtmlTextWriterAttribute.Width, editColumn.Width.Value.ToString());
				}
				writer.RenderBeginTag(HtmlTextWriterTag.Th);
				writer.RenderEndTag();
			}

			if (deleteColumn != null)
			{
				if (deleteColumn.Width.HasValue)
				{
					writer.AddAttribute(HtmlTextWriterAttribute.Width, deleteColumn.Width.Value.ToString());
				}
				writer.RenderBeginTag(HtmlTextWriterTag.Th);
				writer.RenderEndTag();
			}

			foreach (DataGridColumn<T> column in dataColumns)
			{
				if (column.Width.HasValue)
				{
					writer.AddAttribute(HtmlTextWriterAttribute.Width, column.Width.Value.ToString());
				}

				writer.RenderBeginTag(HtmlTextWriterTag.Th);

				if (column.AllowSorting)
				{
					var currentAction = (string)helper.ViewContext.RouteData.Values["action"];

					string sortValue = column.Expression.ExtractPropertyName();

					if (ajaxSorting)
					{
						var ajaxHelper = new AjaxHelper(helper.ViewContext, helper.ViewDataContainer);

						var link = ajaxHelper.ActionLink(
							column.Name,
							currentAction,
							new { page = 0, sort = sortValue, filter = filter },
							new AjaxOptions { UpdateTargetId = divToUpdate });

						writer.Write(link);
					}
					else
					{
						var link = helper.ActionLink(column.Name, currentAction, new { page = 0, sort = sortValue, filter = filter });
						writer.Write(link);
					}
				}
				else
				{
					writer.Write(column.Name);
				}

				writer.RenderEndTag();
			}
			writer.RenderEndTag();
		}

		private static void RenderRow<T>(
			HtmlHelper helper,
			HtmlTextWriter writer,
			IList<DataGridColumn<T>> dataColumns,
			T item,
			DataGridEditColumn<T> editColumn,
			DataGridDeleteColumnBase<T> deleteColumn)
			where T : class
		{
			writer.RenderBeginTag(HtmlTextWriterTag.Tr);

			if (editColumn != null)
			{
				writer.AddAttribute(HtmlTextWriterAttribute.Align, "center");
				writer.RenderBeginTag(HtmlTextWriterTag.Td);

				string propertyName = ExpressionHelperExtension.GetInputName<T, string>(editColumn.Key); //ExpressionHelper.GetInputName<T, string>(editColumn.Key);

				PropertyInfo pi = item.GetType().GetProperty(propertyName);

				object propertyValue = pi.GetValue(item, null);

				var link = helper.ActionLink(
					editColumn.Text,
					editColumn.Action,
					editColumn.Controller,
					new { id = propertyValue.ToString() },
					new { });

				writer.Write(link);

				writer.RenderEndTag();
			}

			if (deleteColumn != null)
			{
				writer.AddAttribute(HtmlTextWriterAttribute.Align, "center");
				writer.RenderBeginTag(HtmlTextWriterTag.Td);

				string propertyName = ExpressionHelperExtension.GetInputName<T, string>(deleteColumn.Key); //ExpressionHelper.GetInputName<T, string>(deleteColumn.Key);

				PropertyInfo pi = item.GetType().GetProperty(propertyName);

				object properyValue = pi.GetValue(item, null);

				if (deleteColumn is DataGridAjaxDeleteColumn<T>)
				{
					DataGridAjaxDeleteColumn<T> column = deleteColumn as DataGridAjaxDeleteColumn<T>;

					var ajaxHelper = new AjaxHelper(helper.ViewContext, helper.ViewDataContainer);

					var link = ajaxHelper.ActionLink(
						column.Text,
						column.Action,
						column.Controller,
						new { id = properyValue.ToString() },
						new AjaxOptions
						{
							Confirm = column.ConfirmMessage,
							HttpMethod = "Delete",
							UpdateTargetId = column.DivToUpdate
						});

					writer.Write(link);
				}
				else
				{
					var link = helper.ActionLink(
						deleteColumn.Text,
						deleteColumn.Action,
						deleteColumn.Controller,
						new { id = properyValue.ToString() },
						new { });

					writer.Write(link);
				}

				writer.RenderEndTag();
			}

			foreach (DataGridColumn<T> column in dataColumns)
			{
				writer.RenderBeginTag(HtmlTextWriterTag.Td);

				var value = column.Expression.ExtractPropertyValue<T>(item);

				writer.Write(helper.Encode(value.ToString()));

				writer.RenderEndTag();
			}
			writer.RenderEndTag();
		}

		private static void RenderPagerRow<T>(
			HtmlHelper helper,
			HtmlTextWriter writer,
			PagedList<T> items,
			int columnCount,
			bool ajaxPagination,
			string divToUpdate)
			where T : class
		{
			// Don't show paging UI for only 1 page  
			if (items.TotalPageCount == 1)
				return;

			// Render page numbers  
			writer.RenderBeginTag(HtmlTextWriterTag.Tr);
			writer.AddAttribute(HtmlTextWriterAttribute.Colspan, columnCount.ToString());
			writer.RenderBeginTag(HtmlTextWriterTag.Td);
			var currentAction = (string)helper.ViewContext.RouteData.Values["action"];
			for (var i = 0; i < items.TotalPageCount; i++)
			{
				if (i == items.PageIndex)
				{
					writer.Write(String.Format("<strong>{0}</strong>&nbsp;", i + 1));
				}
				else
				{
					var linkText = String.Format("{0}", i + 1);

					if (ajaxPagination)
					{
						var ajaxHelper = new AjaxHelper(helper.ViewContext, helper.ViewDataContainer);

						var link = ajaxHelper.ActionLink(
							linkText,
							currentAction,
							new { page = i, sort = items.SortExpression, filter = items.Filter },
							new AjaxOptions { UpdateTargetId = divToUpdate }
							);

						writer.Write(link + "&nbsp;");
					}
					else
					{
						var link = helper.ActionLink(linkText, currentAction, new { page = i, sort = items.SortExpression, filter = items.Filter });

						writer.Write(link + "&nbsp;");
					}
				}
			}
			writer.RenderEndTag();
			writer.RenderEndTag();
		}


	}
}

